<template>
  <div>
    <fks-upload
      ref="upload"
      class="upload-demo"
      action=""
      :on-remove="handleRemove"
      :on-success="handleSuccess"
      :on-error="handleError"
      :on-preview="handlePreView"
      :on-download="handleDownLoad"
      :show-download="showDownload"
      :http-request="handleUpload"
      v-bind="$attrs"
      :on-change="handleFileChange"
      :file-list="fileListTemp"
      v-on="$listeners"
    >
      <template>
        <slot>
          <fks-button size="small" plain icon="fks-icon-upload-line"
            >上传
          </fks-button>
        </slot>
      </template>
      <template slot="tip">
        <slot name="tip">
          <span
            class="fks-upload__tip fks-upload-tip"
          >{{ count }}个文件已上传</span>
        </slot>
      </template>
    </fks-upload>
    <fks-dialog
      :visible.sync="dialogVisible"
      :title="file.name"
      append-to-body
      class="dialog-8vh"
    >
      <div style="height: calc(100vh - 330px)">
        <pre-view
          :key="file.uid"
          :file-token="file.response && file.response.fileToken"
        />
      </div>
    </fks-dialog>
  </div>
</template>
<script>
import { changeFileG9s, getFileToken } from './api'
import { uuid } from '@/utils/util'
import axios from 'axios'
import { getUrl, getSign } from '@/utils/request/sign'
import PreView from '@/components/PreView/index.vue'
import emitter from 'fawkes-lib/src/mixins/emitter'
import request from '@/utils/request/index.js'
const cancelTokenObj = new Map()
export default {
  name: 'FormUpload',
  componentName: 'FormUpload',
  components: {
    PreView
  },
  mixins: [emitter],
  inject: {
    fksForm: {
      default: ''
    },
    fksFormItem: {
      default: ''
    }
  },
  props: {
    value: {
      type: String,
      required: true
    },
    disabled: {
      type: Boolean,
      default: false
    }
  },
  data() {
    return {
      showDownload: false,
      fileTokenList: [],
      fileTokenListCache: [], //每次value变化缓存上一次的文件列表
      fileListTemp: [],
      //预览
      file: {}, //预览文件数据
      dialogVisible: false,
      refresh: true
    }
  },
  computed: {
    count() {
      return this.fileListTemp.length
    }
  },
  watch: {
    value: {
      immediate: true,
      handler(newVal) {
        this.fileTokenListCache = []
        if (!newVal) {
          this.fileTokenList = []
          this.fileListTemp = []
          return
        }
        //setG9s会改变value,一般来说这个时候都是会关闭弹窗的,此时默认不去重新获取文件
        if (!this.refresh) {
          this.refresh = true
          return
        }
        let postData = {
          g9s: [newVal]
        }
        getFileToken(postData).then((res) => {
          if (res.status) {
            let fileTokenList = res.data
            const fileList = []
            fileTokenList.forEach((item) => {
              let fileItem = {
                name: item.fileName,
                url: item.fileToken,
                size: item.size,
                response: item
              }
              fileList.push(fileItem)
              this.fileTokenList.push(item.fileToken)
              this.fileTokenListCache.push(item.fileToken)
            })
            this.fileListTemp = fileList
            this.$emit('fileChange', '', fileList, fileList.length)
          }
        })
      }
    }
  },
  created() {
    this.$on('setG9s', this.setG9s)
  },
  methods: {
    setG9s(refresh = false) {
      //setG9s的时候默认不去重新获取文件
      this.refresh = refresh
      if (
        this.fileTokenListCache.toString() === this.fileTokenList.toString()
      ) {
        return
      }
      if (this.fileTokenList.length) {
        const g9s = uuid()
        this.$emit('input', g9s)
        //将g9s 和文件
        changeFileG9s(g9s, this.fileTokenList)
      } else {
        this.$emit('input', '')
      }
    },
    handleSuccess(response, file, fileList) {
      this.dispatch('FormCenter', 'uploaded', file.uid)
      this.showDownload = true
      this.fileTokenList.push(file.response.fileToken)
      this.fileListTemp = fileList
      //给FksFormItem派发change事件，触发表单项的校验
      this.dispatch('FksFormItem', 'fks.form.change')
    },
    handleError(err, file, fileList) {
      this.dispatch('FormCenter', 'uploaded', file.uid)
      this.showDownload = true
      this.fileListTemp = fileList
      this.dispatch('FksFormItem', 'fks.form.change')
    },
    handleRemove(file, fileList) {
      const fileId = file.uid
      //如果文件在上传中的话，则取消上传请求
      const source = cancelTokenObj.get(fileId)
      source && source.cancel()
      //派发上传结束的事件
      this.dispatch('FormCenter', 'uploaded', fileId)
      //没有response表示没上传成功，或者上传被取消了。直接return
      if (!file.response) {
        return
      }
      this.fileTokenList = this.fileTokenList.filter((item) => {
        return item !== file.response.fileToken
      })
      this.fileListTemp = fileList
      //派发文件列表状态变化事件
      this.$emit('fileChange', file, fileList, fileList.length)
      //给FksFormItem派发change事件，触发表单项的校验
      this.dispatch('FksFormItem', 'fks.form.change')
    },
    handleUpload(file) {
      let formData = new FormData()
      formData.append('file', file.file)
      const fileId = file.file.uid
      //生成取消请求的token,方便在handleRemove取消上传时结束请求
      const CancelToken = axios.CancelToken
      const source = CancelToken.source()
      cancelTokenObj.set(fileId, source)
      //给FormCenter/index.vue派发事件，表示有文件上传中。
      this.dispatch('FormCenter', 'uploading', fileId)
      //隐藏下载按钮
      this.showDownload = false
      request({
        url: '/sys-storage/upload',
        method: 'post',
        headers: {
          'Content-Type': 'multipart/form-data'
        },
        params: getSign(),
        data: formData,
        timeout: 0,
        cancelToken: source.token,
        onUploadProgress: (progressEvent) => {
          let percent = ((progressEvent.loaded / progressEvent.total) * 100) | 0
          //调用onProgress方法来显示进度条，需要传递个对象 percent为进度值
          file.onProgress({ percent: percent })
        }
      })
        .then((res) => {
          //上传成功后，派发上传成功事件
          file.onSuccess(res.data)
        })
        .catch((err) => {
          console.log(err)
          file.onError(err)
        })
    },
    handleDownLoad(file) {
      let link = document.createElement('a')
      link.href = `${this.VUE_APP_DOWNLOAD_API}?${getUrl({
        f8s: file.response.fileToken
      })}`
      document.body.appendChild(link)
      link.click()
      document.body.removeChild(link)
    },
    handlePreView(file) {
      this.file = file
      this.dialogVisible = true
    },
    handleFileChange(file, fileList) {
      this.$emit('fileChange', file, fileList, fileList.length)
    }
  }
}
</script>
